package com.chiyoyo.response.i18n;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.MessageSource;
import org.springframework.context.NoSuchMessageException;
import org.springframework.context.i18n.LocaleContextHolder;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

/**
 * @author chilei
 * 封装返回对象
 */
@Slf4j
public class ResultHelper {

    private static MessageSource messages;

    @Resource
    private MessageSource messageSource;

    @PostConstruct
    private void init() {
        messages = messageSource;
    }

    /**
     * 接口请求成功
     */
    public static <T> ResultI18n<T> success() {
        return success(null);
    }

    /**
     * 接口请求成功
     *
     * @param data 返回接口数据
     */
    public static <T> ResultI18n<T> success(T data) {
        return createResult(200, "成功", data);
    }

    /**
     * 失败
     */
    public static <T> ResultI18n<T> fail() {
        return fail(-1);
    }

    /**
     * 业务错误
     *
     * @param errCode 错误码
     */
    public static <T> ResultI18n<T> fail(Integer errCode) {
        return fail(errCode, null);
    }

    /**
     * 业务错误，接口数据
     *
     * @param errCode 错误码
     * @param data    接口数据
     */
    public static <T> ResultI18n<T> fail(Integer errCode, T data) {
        return getMessage(errCode, data);
    }

    /**
     * @param iErrorCodeEnum 接口错误枚举
     * @return 错误信息
     */
    public static <T> ResultI18n<T> fail(IErrorCodeEnum iErrorCodeEnum) {
        return fail(iErrorCodeEnum, null);
    }

    /**
     * @param iErrorCodeEnum 接口错误枚举
     * @param data           接口数据
     * @return 错误信息
     */
    public static <T> ResultI18n<T> fail(IErrorCodeEnum iErrorCodeEnum, T data) {
        return getMessage(iErrorCodeEnum, data);
    }

    /**
     * @param errCode 错误码
     * @param msg     错误信息
     * @param data    接口数据
     */
    public static <T> ResultI18n<T> failResult(Integer errCode, String msg, T data) {
        return new ResultI18n<>(errCode, msg, data);
    }

    /**
     * @param errCode 错误码
     * @param msg     错误信息
     */
    public static <T> ResultI18n<T> failResult(Integer errCode, String msg) {
        return failResult(errCode, msg, null);
    }

    /**
     * 格式化返回，msg里有%s占位符
     *
     * @param errCode 响文code
     * @param format  %s占位符的数据
     */
    public static <T> ResultI18n<T> failFormat(Integer errCode, Object... format) {
        return getMessage(errCode, null, format);
    }

    /**
     * 格式化返回，msg里有%s占位符
     *
     * @param iErrorCodeEnum 接口错误枚举
     * @param format         %s占位符的数据
     */
    public static <T> ResultI18n<T> failFormat(IErrorCodeEnum iErrorCodeEnum, Object... format) {
        return getMessage(iErrorCodeEnum, null, format);
    }

    /**
     * 获取国际化消息
     *
     * @param errCode        错误码
     * @param defaultMessage 默认消息
     * @param format         格式化参数
     * @return 国际化消息
     */
    private static String getI18nMessage(Integer errCode, String defaultMessage, Object... format) {
        String message;
        try {
            message = messages.getMessage(errCode.toString(), null, LocaleContextHolder.getLocale());
        } catch (NoSuchMessageException e) {
            message = defaultMessage;
            log.warn("i18n message err: {}", e.getMessage());
        }
        return String.format(message, format);
    }

    /**
     * 创建结果对象
     *
     * @param errCode        错误码
     * @param defaultMessage 默认消息
     * @param data           数据
     * @param format         格式化参数
     * @param <T>            返回数据类型
     * @return ResultI18n
     */
    private static <T> ResultI18n<T> createResult(Integer errCode, String defaultMessage, T data, Object... format) {
        String message;
        if ("zh".equals(LocaleContextHolder.getLocale().getLanguage())) {
            message = errCode == 200 ? "成功" : defaultMessage;
        } else {
            message = getI18nMessage(errCode, defaultMessage, format);
        }
        return new ResultI18n<>(errCode, message, data);
    }

    /**
     * 获取带有国际化的结果
     *
     * @param errCode 错误码
     * @param data    数据
     * @param format  格式化参数
     * @param <T>     返回数据类型
     * @return ResultI18n
     */
    public static <T> ResultI18n<T> getMessage(Integer errCode, T data, Object... format) {
        return createResult(errCode, "发生了未知的错误，请联系客服处理", data, format);
    }

    /**
     * 获取带有国际化的结果
     *
     * @param iErrorCodeEnum 接口错误枚举
     * @param data           数据
     * @param format         格式化参数
     * @param <T>            返回数据类型
     * @return ResultI18n
     */
    public static <T> ResultI18n<T> getMessage(IErrorCodeEnum iErrorCodeEnum, T data, Object... format) {
        Integer errCode = iErrorCodeEnum.getCode();
        String defaultMessage = iErrorCodeEnum.getMsg();
        return createResult(errCode, defaultMessage, data, format);
    }
}

